#pragma once
#include "log.hpp"
#include<sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string>
#include"threadpool.hpp"
#include"Task.hpp"
const int defaultfd = -1;
const uint16_t defaultport = 8808;
const std::string defaultip = "0.0.0.0";
int backlog = 5;
extern Log lg;
enum
{
    SOCK_ERR = 2,
    BIND_ERR,
    LISTEN_ERR
};
class TcpServer;
class ThreadData
{
    public:
    ThreadData(const std::string ip,const uint16_t port,const int sockfd, TcpServer*ts)
    :ip_(ip),port_(port),sockfd_(sockfd),this_(ts)
    {

    }
    public:
    std::string ip_;
    uint16_t port_;
    int sockfd_;
    TcpServer* this_;
};
class TcpServer
{
public:
    TcpServer(const uint16_t &port = defaultport, const std::string &ip = defaultip)
        : listen_fd(defaultfd), port_(port), ip_(defaultip)
    {
    }
    void InitServer() // 初始化服务器
    {
        // 1.创建套接字
        listen_fd = socket(AF_INET, SOCK_STREAM, 0);
        if (listen_fd < 0)
        {
            lg(FATAL, "Make socket faile!! errno is: %d, errstring is:%s", errno, strerror(errno));
            exit(SOCK_ERR);
        }
        lg(INFO, "Sock sucess!!!");
        // 2.准备数据
        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));        // 初始化sockaddr_in 结构体
        inet_aton(ip_.c_str(), &local.sin_addr); // 串转地址
        local.sin_family = AF_INET;
        local.sin_port = htons(port_);
        socklen_t len = sizeof(local);
        // 3.绑定套接字
        if (bind(listen_fd, (sockaddr *)&local, len) < 0)
        {
            lg(FATAL, "Bind fail!! errno is:%d , errstring is: %s ", errno, strerror(errno));
            exit(BIND_ERR);
        }
        lg(INFO, "Bind sucess!! ");
        // 4.监视，保持等待被链接状态
        int n = listen(listen_fd, backlog);
        if (n < 0)
        {
            lg(FATAL, "Listen fail!! errno is: %d, errstring is:%s ", errno, strerror(errno));
            exit(LISTEN_ERR);
        }
        lg(INFO, "Linsten sucess!!");
    }
    // void Service(const int &sockfd, const std::string &clientip, const uint16_t &clientport)
    // {
    //     // 1.读信息
    //     char buffer[1024];
    //     ssize_t n = read(sockfd, buffer, sizeof(buffer));
    //     if (n > 0)
    //     {
    //         buffer[n] = '\0';
    //         std::string message=buffer;
    //         std::cout<<"client say@"<<message<<std::endl;
    //         std::string echo_message = "Server get a message:";
    //         echo_message += buffer;
    //         write(sockfd, echo_message.c_str(), echo_message.size());
    //     }
    // }
//    static void* Routine(void*args)
//     {
//         pthread_detach(pthread_self());
//         ThreadData*td=static_cast<ThreadData*>(args);
//         td->this_->Service(td->sockfd_,td->ip_,td->port_);
//         delete td;
//         return nullptr;
//     }
    void Start() // 开始运行服务器
    {
        threadpool<Task>::GetInstacne()->start();//线程跑起来
        for (;;)
        {
            // 1.获取新链接
        struct sockaddr_in client; // 获取对方信息
        socklen_t len = sizeof(client);
            int sock_fd = accept(listen_fd, (sockaddr *)&client, &len); // listen_fd单个拉客小哥（拉不到继续拉），拉到了sock_fd提供服务，可有多个sock_fd
            if (sock_fd < 0)
            {
                lg(WARNING, "Accept fail!! errno is:%d, errstring is: %s", errno, strerror(errno));
                continue;
            }
            // 获取新连接成功，2.通信，提供服务
            char buffer[32];
            inet_ntop(AF_INET, &client.sin_addr, buffer, sizeof(client)); // 地址（客户端的ip地址）转串
            std::string clientip = buffer;
            uint16_t clientport = ntohs(client.sin_port); // 网络转主机字节序

    std::cout<<"get a link! clientip is:"<<clientip<<" ,clientport is: "<<clientport<<" ,sock_fd is"<<sock_fd<<std::endl;
            //version 1： 单进程
            //Service(sock_fd, clientip, clientport); // 提供服务
            
            //version 2：多进程
        //    pid_t pid= fork();
        //    if(pid==0)
        //    {
        //     //child
        //     close(listen_fd);//子进程不需要linstensock
        //     if(fork()>0)exit(0);//创建子进程并终止自己，让父进程快速回收
        //     Service(sock_fd, clientip, clientport);//孙子进程去执行服务变成孤儿进程，由os回收
        //     close(sock_fd);
        //     exit(0);
        //    }
        //    //farther
        //    close(sock_fd);
        //    waitpid(pid,nullptr,0);

        //version 3: 多线程
        // ThreadData*td=new ThreadData(clientip, clientport,sock_fd,this);
        // pthread_t pid;
        // pthread_create(&pid,nullptr,Routine,td);

        //vesion:4 线程池
        Task t(sock_fd,clientport,clientip);//获取数据,构建任务
        threadpool<Task>::GetInstacne()->push(t);//扔任务到线程池里
        }
    }

    ~TcpServer()
    {
    }

private:
    int listen_fd;   // 套接字返回的文件描述符
    uint16_t port_;  // 端口
    std::string ip_; // ip
};